package com.example.java_chatroom.api;

import com.example.java_chatroom.component.OnlineUserManager;
import com.example.java_chatroom.mapper.FriendMapper;
import com.example.java_chatroom.mapper.MessageMapper;
import com.example.java_chatroom.mapper.MessageSessionMapper;
import com.example.java_chatroom.model.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.List;

@Component
@Slf4j
public class WebSocketAPI extends TextWebSocketHandler {
    @Autowired
    private OnlineUserManager onlineUserManager;

    private ObjectMapper objectMapper = new ObjectMapper();

    @Resource
    private MessageSessionMapper messageSessionMapper;
    @Resource
    private MessageMapper messageMapper;

    @Resource FriendMapper friendMapper;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.info("WebSocketAPI 连接成功");
        User user = (User) session.getAttributes().get("user");
        if(user == null) {
            return;
        }
        log.info("获取到的user: " + user);
        //把键值对存起来
        onlineUserManager.online(user.getUserId(), session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        log.info("WebSocketAPI 收到消息" + message.toString());
        // 处理消息的接收, 转发, 以及消息的
        //1.先获取到当前用户的信息
        User user = (User) session.getAttributes().get("user");
        if(user == null) {
            log.info("[WebSocketAPI] user==null 未登录用户, 无法进行消息转发!");
            return;
        }
        //2.正对请求进行解析, 把json格式的字符串转成java对象
        MessageRequest req = objectMapper.readValue(message.getPayload(), MessageRequest.class);
        if(req.getType().equals("message") ) {
            //进行消息转发
            transferMessage(user, req);
        }else if(req.getType().equals("newFriend")) {
            //进行新好友的处理
            handleNewFriendMessage(user, req);
        }else {
            log.info("[WebSocketAPI] user==null req.type 有误!" + message.getPayload());
        }
    }

    //这个方法用来处理用户发送的好友申请消息的处理
    private void handleNewFriendMessage(User user, MessageRequest req) throws IOException {
        System.out.println("好友申请处理: " + req);
        //往数据库中存放好友请求
        friendMapper.addFriendApplication(user.getUserId(), req.getSessionId(), req.getContent());
        WebSocketSession socketSession = onlineUserManager.getSession(req.getSessionId());
        if(socketSession != null) {
            MessageResponse messageResponse = new MessageResponse();
            messageResponse.setType("newFriend");
            messageResponse.setFromId(user.getUserId());
            messageResponse.setFromName(user.getUsername());
            messageResponse.setContent(req.getContent());

            //把java对象转为字符串
            String respJson = objectMapper.writeValueAsString(messageResponse);
            log.info("[handleNewFriendMessage] respJson:" + respJson);
            socketSession.sendMessage(new TextMessage(respJson));
        }

    }

    //通过这个方法来完成消息的实际转发
    //第一个参数表示这个要转发的消息, 是从谁那里来的
    private void transferMessage(User fromUser, MessageRequest req) throws IOException {
        //1.先构造一个待转发的对象 MessageResponse
        MessageResponse messageResponse = new MessageResponse();
        messageResponse.setType("message");
        messageResponse.setFromId(fromUser.getUserId());
        messageResponse.setFromName(fromUser.getUsername());
        messageResponse.setSessionId(req.getSessionId());
        messageResponse.setContent(req.getContent());
        // 把java 对象转为 json 字符串
        String respJson = objectMapper.writeValueAsString(messageResponse);
        log.info("[transferMessage] respJson:" + respJson);
        //2.根据请求中的 sessionId, 获取这个 MessageSession 中都有哪些用户, 通过查数据库可得
        List<Friend> friends = messageSessionMapper.getFriendsBySessionId(req.getSessionId(), -1);
        //3.循环遍历上述的列表, 给列表中的每个用户都发一个响应消息
        // 注意: 一个会话中可能有多个用户(群聊)
        System.out.println(friends.toString());
        for(Friend friend : friends) {
            // 知道了每个用户的userId, 进一步查询OnlineUserManager, 就知道了对应的 webSocketSession
            WebSocketSession webSocketSession = onlineUserManager.getSession(friend.getFriendId());
            if(webSocketSession == null) {
                //如果用户未在线, 则不发送
                continue;
            }
            webSocketSession.sendMessage(new TextMessage(respJson));

        }
        //4.转发的消息, 还需要放在数据库
        // 需要往 message 表里写一条记录
        Message message = new Message();
        message.setFromId(fromUser.getUserId());
        message.setContent(req.getContent());
        message.setSessionId(req.getSessionId());

        messageMapper.add(message);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.info("WebSocketAPI 连接异常" + exception.toString());

        User user = (User) session.getAttributes().get("user");
        if(user == null) {
            return;
        }
        onlineUserManager.offline(user.getUserId(), session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        log.info("WebSocketAPI 连接关闭" + status);

        User user = (User) session.getAttributes().get("user");
        if(user == null) {
            return;
        }
        onlineUserManager.offline(user.getUserId(), session);

    }
}
